#pragma once
#include "OUniform.h"
#include "Config.h"

namespace Light {

enum Type { Directional, Point, Spot };

class Directional {
public:
	static Directional* get() {
		static auto* instance = new Directional;
		return instance;
	}

	void setWorldDirection(const P3D& worldDirection) { m_worldDirection = worldDirection; }
	void setColor(const CColor& color) { m_color = color; }
	void setIntensity(float intensity) { m_intensity = intensity; }

	void setUniform(OUniform& uniform, Switch status) {
		if (Switch::On == status) {
			uniform.addStruct("directional",
				Field("worldDirection", m_worldDirection),
				Field("intensity", m_intensity),
				Field("color", m_color)
			);
		} else
			uniform.removeStruct("directional", { "worldDirection", "intensity", "color" });
	}

private:
	Directional() = default;

	P3D m_worldDirection = Config::Light_Directional_WorldDirection;
	CColor m_color = Config::Light_Directional_Color;
	float m_intensity = Config::Light_Directional_Intensity;
};

class Point {
public:
	static Point* get() {
		static auto* instance = new Point;
		return instance;
	}

	void setPosition(const P3D& position) { m_position = position; }
	void setColor(const CColor& color) { m_color = color; }
	void setIntensity(float intensity) { m_intensity = intensity; }
	void setConstAtt(float consAtt) { m_constAtt = consAtt; }
	void setLinearAtt(float linearAtt) { m_linearAtt = linearAtt; }
	void setQuadAtt(float quadAtt) { m_quadAtt = quadAtt; }

	void setUniform(OUniform& uniform, Switch status) {
		if (Switch::On == status) {
			uniform.addStruct("point",
				Field("position", m_position),
				Field("intensity", m_intensity),
				Field("constAtt", m_constAtt),
				Field("linearAtt", m_linearAtt),
				Field("quadAtt", m_quadAtt),
				Field("color", m_color)
			);
		} else
			uniform.removeStruct("point", { "position", "intensity", "constAtt", "linearAtt", "quadAtt", "color" });
	}

private:
	Point() = default;

	P3D m_position = Config::Light_Point_Position;
	CColor m_color = Config::Light_Point_Color;
	float m_intensity = Config::Light_Point_Intensity;
	float m_constAtt = Config::Light_Point_ConstAtt;
	float m_linearAtt = Config::Light_Point_LinearAtt;
	float m_quadAtt = Config::Light_Point_QuadAtt;
};

class Spot {
public:
	static Spot* get() {
		static auto* instance = new Spot;
		return instance;
	}

	void setPosition(const P3D& position) { m_position = position; }
	void setColor(const CColor& color) { m_color = color; }
	void setIntensity(float intensity) { m_intensity = intensity; }
	void setLocalDirection(const P3D& localDirection) { m_localDirection = localDirection; }
	void setCutOffAngle(float cutOffAngle) { m_cutOffAngle = cutOffAngle; }
	void setConstAtt(float constAtt) { m_constAtt = constAtt; }
	void setLinearAtt(float linearAtt) { m_linearAtt = linearAtt; }
	void setQuadAtt(float quadAtt) { m_quadAtt = quadAtt; }

	void setUniform(OUniform& uniform, Switch status) {
		if (Switch::On == status) {
			uniform.addStruct("point",
				Field("position", m_position),
				Field("intensity", m_intensity),
				Field("localDirection", m_localDirection),
				Field("cutOffAngle", m_cutOffAngle),
				Field("constAtt", m_constAtt),
				Field("linearAtt", m_linearAtt),
				Field("quadAtt", m_quadAtt),
				Field("color", m_color)
			);
		} else
			uniform.removeStruct("spot", { "position", "intensity", "localDirection", "cutOffAngle", "constAtt", "linearAtt", "quadAtt", "color" });
	}

private:
	Spot() = default;

	P3D m_position;
	CColor m_color;
	float m_intensity;
	P3D m_localDirection;
	float m_cutOffAngle;
	float m_constAtt;
	float m_linearAtt;
	float m_quadAtt;
};

}// end namespace